package java01;

import org.junit.Test;

import javax.swing.Timer;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

//在声明函数式接口（声明只有一个抽象方法的接口）的时候，可以使用lambda表达式，如Comparator
public class JavaLambda {

    @Test
    public void lambdaTest01(){
        Person zhangsan = new Person("zhangsan",28);
        Person lisi = new Person("lisi", 35);
        Person wangwu = new Person("wangwu", 54);
        Person[] persons=new Person[]{zhangsan,lisi,wangwu};
        Arrays.sort(persons,(person1,person2) -> person1.getName().length()-person2.getName().length());//lambda有参表达式，可以推导出某个方法
        System.out.println(Arrays.toString(persons));
//        () -> {System.out.println(1);}//lambda无参表达式
        Timer timer = new Timer(10000, event -> System.out.println(new Date()));//推导唯一参数，省略小括号
        timer.start();
        JOptionPane.showMessageDialog(null,"Quit program?");
        System.exit(0);
    }

    @Test
    public void lambdaTest02(){
        ArrayList<String> list = new ArrayList<>();
        list.add("xiaowang");
        list.add("xiaozhang");
        list.add("xiaoli");
        Stream<Person> stream = list.stream().map(Person::new);//通过lambda和构造器将一个List<String>转换成List<Person>
        List<Person> people = stream.collect(Collectors.toList());
        System.out.println(Arrays.toString(people.toArray()));

        Stream<Person> streamArr = list.stream().map(Person::new);//通过lambda和构造器将一个List<String>转换成Person[]
        Person[] persons = streamArr.toArray(Person[]::new);
        System.out.println(Arrays.toString(persons));

        List<Map<String,Object>> mapList=new ArrayList<>();
        HashMap<String, Object> map1 = new HashMap<>();
        map1.put("name","laowang");
        map1.put("age",20);
        HashMap<String,Object> map2 = (HashMap<String, Object>) map1.clone();
        mapList.add(map1);
        mapList.add(map2);
        Stream<Person> streams = mapList.stream().map(Person::new);//通过lambda和构造器将一个List<Map<String,String>>转换成List<Person>或Person[]
        Person[] ps = streams.toArray(Person[]::new);
        System.out.println(Arrays.toString(ps));
    }

    public void lambdaTest03(String text,int delay){
        int[] counter=new int[1];//由于内部类引用的局部变量是不可变的，所以补救办法是创建一个长度为1的数组
        ActionListener listener= e -> {
            System.out.println(text);//方法的参数传入匿名内部类中，该变量叫做自由变量
            Toolkit.getDefaultToolkit().beep();
            counter[0]++;
            System.out.println(this);//其中的this是JavaLambda类
        };
        new Timer(delay,listener).start();
        System.out.println(counter[0]);
    }

    private static void lambdaTest04(int n, Runnable action){
        for(int i=0;i<n;i++){
            action.run();
        }
    }

    private static void lambdaTest05(int n, IntConsumer action){
        for(int i=0;i<n;i++){
            action.accept(i);
        }
    }

    @Test
    public void lambdaTest06(){
        Person zhangsan = new Person("zhangsan",28);
        Person lisi = new Person("lisi", 35);
        Person wangwu = new Person(null, 54);
        Person[] persons=new Person[]{zhangsan,lisi,wangwu};
        Arrays.sort(persons,Comparator.comparing(Person::getName));//键提取器构造比较器,名字排序
        Arrays.sort(persons,Comparator.comparing(Person::getName).thenComparing(Person::getAge));//构造两个比较器，先名字排序，后年龄排序

        Arrays.sort(persons,Comparator.comparing(Person::getName,(s,t)->Integer.compare(s.length(),t.length())));//根据名称长度排序，
        Arrays.sort(persons, Comparator.comparingInt(person -> person.getName().length()));
        //如果函数返回null，可能要用到nullsFirst和nullsLast适配器。而适配器需要一个比较器，naturalOrder方法可以为任何实现了Comparable的类建立一个比较器
        Arrays.sort(persons,Comparator.comparing(Person::getName,Comparator.nullsFirst(Comparator.naturalOrder())));//reversed逆序比较，等同reverseOrder
    }

    public static void main(String[] args) {
        lambdaTest04(10,() -> System.out.println("HelloWorld"));//调用只有一个无参方法的接口
        lambdaTest05(10,i -> System.out.println("打印"+(9-i)));//调用只有一个有一个参数方法的接口
        JavaLambda javaLambda = new JavaLambda();
        javaLambda.lambdaTest03("Hello",1000);
        JOptionPane.showMessageDialog(null,"Quit program?");
        System.exit(0);
    }
}
